package control;

import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.JOptionPane;
import org.jfree.ui.RefineryUtilities;
import GUI.Chart;
import GUI.MainFrame;
import entities.User;
/**
 * GUI controllers for the Library Manager
 * @author Benny
 *
 */
public class LibraryManagerControllers {
	
	public MainFrame mf;
	public User user;
	
	/**
	 * Create the panel.
	 * @param M main frame of the program
	 */
	public LibraryManagerControllers(MainFrame M){
		mf=M;
		}
	
	/**
	 * Display the appropriate data into the GUI depending on command
	 * @param msg message received from the DataBase
	 */
	public void handleMessage (Object msg){
		@SuppressWarnings("unchecked")
		ArrayList<Object> messages=(ArrayList<Object>) msg;
		String command = (String) messages.get(1);
		/**
		 * Controller for viewing the users who's status should be frozen
		 */
		if(command.equals("ShowUserToFreeze"))
		{
			if(messages.get(2).equals("OK"))
			{
				mf.managerMain.cardManaging.init();
                String[] userToFreeze;
                
                for(int i=3;i<messages.size();i++)
                {
                	userToFreeze = (String[]) messages.get(i);
                	System.out.println(userToFreeze[0]);
                	System.out.println(userToFreeze[1]);
                	System.out.println(userToFreeze[2]);
                	System.out.println(userToFreeze[3]);
                    String[] user = {userToFreeze[0],userToFreeze[1],userToFreeze[2],userToFreeze[3]};
                    mf.managerMain.cardManaging.freezeTableModel.addRow(user);
                }

			}
			else JOptionPane.showMessageDialog(null, "no users for freeze!", "Program", JOptionPane.PLAIN_MESSAGE);
		}
		/**
		 * Controller for freezing all the users who are late in returning a book
		 */
		if(command.equals("FreezeAll"))
		{
			if(messages.get(2).equals("OK"))
				JOptionPane.showMessageDialog(null, "All Users Were Frozen!", "Program", JOptionPane.PLAIN_MESSAGE);
			else JOptionPane.showMessageDialog(null, "Cannot Freeze All", "Program", JOptionPane.PLAIN_MESSAGE);
		}
		/**
		 * Controller for viewing the users who's status is frozen
		 */
		if(command.equals("ViewFrozenUsers"))
		{
			if(messages.get(2).equals("OK"))
			{
                String[] frozen;
            
                for(int i=3;i<messages.size();i++)
                {
                	frozen = (String[]) messages.get(i);
                	System.out.println(frozen[0]);
                	System.out.println(frozen[1]);
                    String[] user = {frozen[0],frozen[1]};
                    mf.managerMain.cardManaging.unfreezeTableModel.addRow(user);
                }
			}
			else JOptionPane.showMessageDialog(null, "no frozen users!", "Program", JOptionPane.PLAIN_MESSAGE);
		}
		/**
		 * Controller for unfreezing a specific user
		 */
		if(command.equals("UnfreezeUser"))
		{
			if(messages.get(2).equals("OK"))
			{
				mf.managerMain.cardManaging.init();
				JOptionPane.showMessageDialog(null, "user was unfrozen successfuly!", "Program", JOptionPane.PLAIN_MESSAGE);
			}
			else
				JOptionPane.showMessageDialog(null, "user was not unfrozen!", "Program", JOptionPane.PLAIN_MESSAGE);
		}
		/**
		 * Controller for changing the status of a specific user's that has graduated
		 */
		if(command.equals("GraduateUser"))
		{
			if(messages.get(2).equals("OK"))
			{
				mf.managerMain.cardManaging.init();
				JOptionPane.showMessageDialog(null, "user was graduated successfuly!", "Program", JOptionPane.PLAIN_MESSAGE);
			}
			else
				JOptionPane.showMessageDialog(null, "cannot be graduated, please Unfreeze first Or Return borrowed books!", "Program", JOptionPane.PLAIN_MESSAGE);
		}
		/**
		 * Controller for viewing the received data into User or Employee Report table 
		 */
		if((command.equals("UserReport")) || (command.equals("EmployeeReport")))
		{
			if(messages.get(2).equals("OK"))
			{
				for (int i = mf.managerMain.reports.searchTableModel1.getRowCount() - 1; i >= 0; i--){ 
					mf.managerMain.reports.searchTableModel1.removeRow(i);
				 }
				User user;

               for(int i=3;i<messages.size();i++)
               {
               	user = (User) messages.get(i);
               	String userID = Integer.toString(user.id);
                String[] userInfo = {userID, user.username, user.phone, user.email, user.password, user.cardStatus};
                mf.managerMain.reports.searchTableModel1.addRow(userInfo);
               }
			}
			else JOptionPane.showMessageDialog(null, "Failed generating Report", "Program", JOptionPane.ERROR_MESSAGE);
		}
		/**
		 * Controller for viewing the data for the generated activity report
		 */
		if(command.equals("Activity"))
		{
			if(messages.get(7).equals("OK"))
			{
				mf.managerMain.activityGUI.lblActive.setText((String) messages.get(2));
				mf.managerMain.activityGUI.lblFrozen.setText((String) messages.get(3));
				mf.managerMain.activityGUI.lblLock.setText((String) messages.get(4));
				mf.managerMain.activityGUI.lblBorrow.setText((String) messages.get(5));
				mf.managerMain.activityGUI.lblDelay.setText((String) messages.get(6));
				
				mf.managerMain.activityGUI.setVisible(true);
			}
			else JOptionPane.showMessageDialog(null, "Failed generating Activity Report", "Program", JOptionPane.ERROR_MESSAGE);
		}
		/**
		 * Controller for viewing the data for the generated Regular or Rated Borrows Report
		 */
		if((command.equals("RegBooks")) || (command.equals("RatedBooks")))
		{
			if(messages.get(2).equals("OK"))
			{
				String avg, median;
				int[] distribution = new int[10];
				int[] values = new int[messages.size()-3];
				for(int i=3;i< messages.size();i++)
					values[i-3]=(int) messages.get(i);

				avg = Float.toString((float) average(values).get(1));
				median = Float.toString((float) median(values).get(1));
		        distribution=(int[])dist(values).get(1);
		        System.out.println(avg+" "+median);
				mf.managerMain.regBorrowGUI.distChart = new Chart("Decimal Distribution",distribution);
				mf.managerMain.regBorrowGUI.distChart.pack();     
				mf.managerMain.regBorrowGUI.distChart.setVisible(true);
				RefineryUtilities.centerFrameOnScreen(mf.managerMain.regBorrowGUI.distChart);  
				mf.managerMain.regBorrowGUI.label.setText(avg);
				mf.managerMain.regBorrowGUI.label_1.setText(median);     
				mf.managerMain.regBorrowGUI.setVisible(true);
			}
			else JOptionPane.showMessageDialog(null, "Couldn't Generate Report", "Program", JOptionPane.ERROR_MESSAGE);
		}
	}
	/**
	 * Calculate the average of given array of values
	 * @param values array of int values 
	 * @return ArrayList containing the calculated average
	 */
	 public static ArrayList<Object> average(int[] values)
     {
             ArrayList<Object> res = new ArrayList<>();
             float average = 0;
             float sum=0;
             
            if(values.length==0)
                    res.add("Fail");
            else
            {
                res.add("OK");
                for (int i=0; i < values.length; i++)
                    sum+= values[i];

                    average = (float)(sum/values.length);
                    res.add(average);
            }
            return res;
     }
	 /**
	  * Calculate the median of a given array of values
	  * @param values array of int values 
	  * @return ArrayList containing the calculated median
	  */
	 public static ArrayList<Object> median(int[] values)
     {
             ArrayList<Object> res = new ArrayList<>();
             float median=0;
            
             if(values.length==0)
                     res.add("Fail");
            else
            {   
                res.add("OK");
                Arrays.sort(values);
                
                if(values.length%2==0)
                        median= (float)(values[values.length/2-1]+values[values.length/2])/2;
                else
                        median=(float) values[(values.length)/2];

                res.add(median);
            }
             return res; 
     }
	 /**
	  * Calculate the decimal distribution of a given array of values
	  * @param values array of int values 
	  * @return ArrayList containing the calculated distribution array
	  */
	 public static ArrayList<Object> dist(int[] values)
     {
             ArrayList<Object> res = new ArrayList<>();
             int[] send = new int[10];
             if(values.length==0)
                     res.add("Fail");
             
            else
            {
                res.add("OK");
                for (int i=0; i < values.length; i++)
                {   
                    int num= values[i];
                    if( num>0 && num<=3) send[0]++;
                    if( num>3 && num<=6) send[1]++;
                    if( num>6 && num<=9) send[2]++;
                    if( num>9 && num<=12) send[3]++;
                    if( num>12 && num<=15) send[4]++;
                    if( num>15 && num<=18) send[5]++;
                    if( num>18 && num<=21) send[6]++;
                    if( num>21 && num<=24) send[7]++;
                    if( num>24 && num<=27) send[8]++;
                    if( num>27 && num<=30) send[9]++;
                }
                res.add(send);
            }
             return res;
     }

}
